package cn.kmsoft.stgeometry.util;

import cn.kmsoft.stgeometry.landm.Block;
import cn.kmsoft.stgeometry.landm.Land;
import cn.kmsoft.stgeometry.landm.LandHeader;
import cn.kmsoft.stgeometry.landm.Ring;
import cn.kmsoft.common.utils.FileUtil;
import cn.kmsoft.common.utils.StringUtil;
import cn.kmsoft.wololo.jts2geojson.GeoJSONReader;
import cn.kmsoft.wololo.jts2geojson.GeoJSONWriter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.index.quadtree.Quadtree;
import org.geotools.data.*;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.shapefile.dbf.DbaseFileHeader;
import org.geotools.data.shapefile.dbf.DbaseFileReader;
import org.geotools.data.shapefile.files.ShpFiles;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.referencing.CRS;
import org.opengis.feature.GeometryAttribute;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.feature.type.PropertyType;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.*;

/*
 * Shapefile操作类
 * */
public class ShpUtil {

    private static int MAX_SHAPE_FIELD_LENGTH = 10;    // Shapefile字段最大(字符)长度

    /**
     * 读取shp文件的字符格式名称，代码来自网络
     *
     * 通常低版本arcmap生成的shp文件格式为gbk；高版本为utf-8.
     * 可通过判断是否包含cpg文件或者读取cpg文件内容获得编码格式
     *
     *
     * @param shppath
     * @return
     */
    public static String getShpCharsetName(String shppath) {
        StringBuilder sb= new StringBuilder(shppath);
        sb.replace(shppath.length()-4, shppath.length(), ".cpg");

        //默认
        String encoding = "GBK";
        File pFile= new File(sb.toString());
        if(!pFile.exists() || !pFile.isFile()) {
            return encoding;
        }

        //解析CharsetName编码名
        try(BufferedReader reader= new BufferedReader(new FileReader(pFile))) {
            String tempString=null;
            //一次读取1行，直到读入null位置为文件结束
            while((tempString=reader.readLine())!=null) {
                //显示行号
                if("UTF-8".equals(tempString.toUpperCase())) {
                    encoding = "UTF-8";
                }else {
                    encoding = tempString.toUpperCase();
                }
                break;
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return encoding;
    }
    /**
     * 读取shp文件的字符格式编码，代码来自网络
     *
     * 通常低版本arcmap生成的shp文件格式为gbk；高版本为utf-8.
     * 可通过判断是否包含cpg文件或者读取cpg文件内容获得编码格式
     *
     *
     * @param shppath
     * @return
     */
    public static Charset getShpCharset(String shppath) {
        StringBuilder sb= new StringBuilder(shppath);
        sb.replace(shppath.length()-4, shppath.length(), ".cpg");

        File pFile= new File(sb.toString());
        String encoding = "GBK";
        if(!pFile.exists() || !pFile.isFile()) {
            return Charset.forName(encoding);
        }

        try(BufferedReader reader= new BufferedReader(new FileReader(pFile))) {
            String tempString=null;
            //一次读取1行，直到读入null位置为文件结束
            while((tempString=reader.readLine())!=null) {
                //显示行号
                if("UTF-8".equals(tempString.toUpperCase())) {
                    encoding = "UTF-8";
                }else {
                    encoding = tempString.toUpperCase();
                }
                break;
            }

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return Charset.forName(encoding);
    }

    public static Map<String, Object> getFieldAndPrj(String shapefile, String encoding) throws Exception {
        Map<String, Object> res = new HashMap<String, Object>();
//		geojson.put("type", "FeatureCollection");
//		JSONArray features = new JSONArray();

        if (StringUtil.isNullOrEmpty(encoding)) {
            encoding = "utf-8";
        }
        URL url = new URL("file:///" + shapefile);
        ShapefileDataStore datastore = new ShapefileDataStore(url);
        datastore.setCharset(Charset.forName(encoding));
        String type = datastore.getTypeNames()[0];
        FeatureSource<SimpleFeatureType, SimpleFeature> source = (FeatureSource<SimpleFeatureType, SimpleFeature>) datastore.getFeatureSource(type);
        FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures();
        FeatureIterator<SimpleFeature> iterator = collection.features();

        List<Map<String, Object>> propList = new ArrayList<Map<String, Object>>();
        while (iterator.hasNext()) {
            Map<String, Object> properties = new HashMap<String, Object>();

            SimpleFeature sf = iterator.next();
            Collection<Property> props = sf.getProperties();
            Iterator<Property> pi = props.iterator();
            while (pi.hasNext()) {
                Property p = pi.next();
                PropertyType pt = p.getType();
                String field = pt.getName().getLocalPart();
                Object val = p.getValue();

                if (val == null) {
                    properties.put(field, "");
                    continue;
                }
                String value = val.toString();
                Class<?> binding = pt.getBinding();

                if (binding.equals(Integer.class)) {
                    properties.put(field, Integer.parseInt(value));

                } else if (binding.equals(Long.class)) {
                    properties.put(field, Long.parseLong(value));

                } else if (binding.equals(Double.class)) {
                    properties.put(field, Double.parseDouble(value));

                } else if (binding.equals(String.class)) {
                    properties.put(field, value);

                }
            }
            propList.add(properties);

        }
        //geojson.put("features", features);
        res.put("propList", propList);
        res.put("prj", datastore.getSchema().getCoordinateReferenceSystem().toWKT());
        iterator.close();
        datastore.dispose();

        return res;
    }

    public static JSONObject toGeoJson(String shapefile) throws Exception {
        return toGeoJson(shapefile, "gbk");
    }


    /**
     * 解析parseShp，返回JSONObject对象
     *
     * @param shpfolder
     * @return
     * @throws Exception
     */
    public static JSONObject readShpByFolder(String shpfolder) throws Exception {

        File inputDir = new File(shpfolder);
        if (StringUtil.isNullOrEmpty(shpfolder) || !inputDir.exists() || !inputDir.isDirectory()) {
            new Exception("输入的shp数据地址有问题-->: " + shpfolder);
        }
        File[] fs = inputDir.listFiles();
        if (fs.length < 4) {
            new Exception("shp 文件内容不全!");
        }

        //查找shp文件名称
        String shpfile = "";
        for (File f : fs) {
            if (f.isFile() && f.getAbsolutePath().toLowerCase().endsWith(".shp")) {
                shpfile = f.getAbsolutePath();
                break;
            }
        }

        String encoding = "GBK";
        return toGeoJson(shpfile, encoding);

    }

    /**
     * 解析shp文件为geojson对象
     *
     * @param shpfilepath shp文件的物理路径  如：E:\temp\gtgis\testtzdk2\tddk.shp
     * @return
     * @throws Exception
     */
    public static JSONObject readShpByFile(String shpfilepath) throws Exception {
        if (StringUtil.isNullOrEmpty(shpfilepath)) {
            return null;
        }
        File f = new File(shpfilepath);
        if (!f.isFile() || !f.exists()) {
            new Exception("输入的shp数据地址有问题-->: " + shpfilepath);
        }
        String folderPath = FileUtil.getPathOfDiskFile(shpfilepath);//物理路径
        String fileNameNoExtention = FileUtil.getFileNameWithNoPathAndExtension(shpfilepath);

        String shxfilepath = folderPath + "/" + fileNameNoExtention + ".shx";
        String dbffilepath = folderPath + "/" + fileNameNoExtention + ".dbf";
        String prjfilepath = folderPath + "/" + fileNameNoExtention + ".prj";
        File shxfile = new File(shxfilepath);
        File dbffile = new File(dbffilepath);
        File prjfile = new File(prjfilepath);

        if (shxfile.exists() && dbffile.exists() && prjfile.exists()) {
            String encoding = "GBK";

            if (StringUtil.isNullOrEmpty(encoding)) {
                encoding = "GBK";
            }
            ShapefileDataStore datastore = new ShapefileDataStore(new File(shpfilepath).toURI().toURL());
            datastore.setCharset(Charset.forName(encoding));
            String typeName = datastore.getTypeNames()[0];

            FeatureSource<SimpleFeatureType, SimpleFeature> feaSource = null;
            feaSource = (FeatureSource<SimpleFeatureType, SimpleFeature>) datastore.getFeatureSource(typeName);
            FeatureCollection<SimpleFeatureType, SimpleFeature> feaCollection = feaSource.getFeatures();

            return toGeoJson(feaCollection, encoding);
        } else {
            return null;
        }
    }

    public static List<Map<String, Object>> readDBFFiles(String path) {
        DbaseFileReader reader = null;
        List<Map<String, Object>> fieldContents = new ArrayList<Map<String, Object>>();
        try {
            reader = new DbaseFileReader(new ShpFiles(path), false, Charset.forName("GBK"));
            DbaseFileHeader header = reader.getHeader();
            int numOfFields = header.getNumFields();
            //
            while (reader.hasNext()) {
                try {
                    Object[] entry = reader.readEntry();
                    Map<String, Object> fieldContent = new HashMap<String, Object>();
                    for (int inIndex = 0; inIndex < numOfFields; inIndex++) {
                        String title = header.getFieldName(inIndex);
                        Object value = entry[inIndex];
                        fieldContent.put(title, value);
                    }
                    fieldContents.add(fieldContent);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (Exception e) {
                    //
                }
            }
        }

        return fieldContents;
    }

    /**
     * 根据Shapefile生成GeoJSON
     *
     * @param path
     * @param encoding
     * @return
     * @throws Exception
     */
    @Deprecated
    public static JSONObject toGeoJson(String path, String encoding) throws Exception {
        JSONObject geojson = new JSONObject();
        JSONArray features = new JSONArray();
        geojson.put("type", "FeatureCollection");
        CoordinateReferenceSystem coordinateReferenceSystem = null;
        if (StringUtil.isNullOrEmpty(encoding)) {
            encoding = "GBK";
        }
        ShapefileDataStore datastore = new ShapefileDataStore(new File(path).toURI().toURL());
        datastore.setCharset(Charset.forName(encoding));
        String typeName = datastore.getTypeNames()[0];

        FeatureSource<SimpleFeatureType, SimpleFeature> feaSource = null;
        feaSource = (FeatureSource<SimpleFeatureType, SimpleFeature>) datastore.getFeatureSource(typeName);

        FeatureCollection<SimpleFeatureType, SimpleFeature> feaCollection = feaSource.getFeatures();
        FeatureIterator<SimpleFeature> feaIter = feaCollection.features();
        while (feaIter.hasNext()) {
            JSONObject feature = new JSONObject();
            JSONObject properties = new JSONObject();
            JSONObject geometry = new JSONObject();
            GeoJSONWriter writer = new GeoJSONWriter();

            SimpleFeature sf = feaIter.next();

            if (coordinateReferenceSystem == null) {
                // geometry属性
                GeometryAttribute geometryAttribute = sf.getDefaultGeometryProperty();
                // 获取坐标参考系信息
                coordinateReferenceSystem = geometryAttribute.getDescriptor().getCoordinateReferenceSystem();
            }
            //1-属性
            Collection<Property> props = sf.getProperties();
            Iterator<Property> proIter = props.iterator();
            while (proIter.hasNext()) {
                Property p = proIter.next();
                PropertyType pt = p.getType();
                String field = pt.getName().getLocalPart();
                Object val = p.getValue();

                if (val == null) {
                    properties.put(field, "");
                    continue;
                }
                String value = val.toString();
                Class<?> binding = pt.getBinding();

                if (binding.equals(Integer.class)) {
                    properties.put(field, Integer.parseInt(value));
                } else if (binding.equals(Long.class)) {
                    properties.put(field, Long.parseLong(value));
                } else if (binding.equals(Double.class)) {
                    properties.put(field, Double.parseDouble(value));
                } else if (binding.equals(String.class)) {
                    properties.put(field, value);
                } else {
                    //1-图形
                    Geometry geom = (Geometry) sf.getDefaultGeometry();
                    cn.kmsoft.wololo.geojson.Geometry geo = writer.write(geom);

                    if (binding.equals(MultiPolygon.class)) {
                        cn.kmsoft.wololo.geojson.MultiPolygon g = (cn.kmsoft.wololo.geojson.MultiPolygon) geo;
                        geometry.put("type", "MultiPolygon");
                        geometry.put("coordinates", g.getCoordinates());

                    } else if (binding.equals(Polygon.class)) {
                        cn.kmsoft.wololo.geojson.Polygon g = (cn.kmsoft.wololo.geojson.Polygon) geo;
                        geometry.put("type", "Polygon");
                        geometry.put("coordinates", g.getCoordinates());

                    } else if (binding.equals(MultiLineString.class)) {
                        cn.kmsoft.wololo.geojson.MultiLineString g = (cn.kmsoft.wololo.geojson.MultiLineString) geo;
                        geometry.put("type", "MultiLineString");
                        geometry.put("coordinates", g.getCoordinates());

                    } else if (binding.equals(LineString.class)) {
                        cn.kmsoft.wololo.geojson.LineString g = (cn.kmsoft.wololo.geojson.LineString) geo;
                        geometry.put("type", "LineString");
                        geometry.put("coordinates", g.getCoordinates());

                    } else if (binding.equals(Point.class)) {
                        cn.kmsoft.wololo.geojson.Point g = (cn.kmsoft.wololo.geojson.Point) geo;
                        geometry.put("type", "Point");
                        geometry.put("coordinates", g.getCoordinates());
                    }
                }
            }
            feature.put("type", "Feature");
            feature.put("properties", properties);
            feature.put("geometry", geometry);

            features.add(feature);
        }
        String name = coordinateReferenceSystem.getName().getCode();
        geojson.put("coordinateReferenceSystem", name);
        geojson.put("features", features);

        feaIter.close();
        datastore.dispose();
        return geojson;
    }

    public static JSONObject toGeoJson2(String path, String encoding) throws Exception {
        JSONObject geojson = new JSONObject();
        geojson.put("type", "FeatureCollection");
        JSONArray features = new JSONArray();

        File shpfile = new File(path);

        FileDataStore store = FileDataStoreFinder.getDataStore(shpfile);
        SimpleFeatureSource featureSource = store.getFeatureSource();
        SimpleFeatureCollection sfc = featureSource.getFeatures();
        SimpleFeatureIterator sfIter = sfc.features();
        while (sfIter.hasNext()) {
            JSONObject feaObject = new JSONObject();
            JSONObject properties = new JSONObject();
            JSONObject geometry = new JSONObject();
            GeoJSONWriter jsonWriter = new GeoJSONWriter();

            SimpleFeature sFea = sfIter.next();
            Collection<Property> props = sFea.getProperties();
            Iterator<Property> propsIter = props.iterator();
            while (propsIter.hasNext()) {
                Property p = propsIter.next();
                PropertyType pt = p.getType();

                String field = pt.getName().getLocalPart();
                Object val = p.getValue();
                if (val == null) {
                    properties.put(field, "");
                    continue;
                }
                String value = val.toString();
                Class<?> binding = pt.getBinding();

                if (binding.equals(Integer.class)) {
                    properties.put(field, Integer.parseInt(value));
                } else if (binding.equals(Long.class)) {
                    properties.put(field, Long.parseLong(value));
                } else if (binding.equals(Double.class)) {
                    properties.put(field, Double.parseDouble(value));
                } else if (binding.equals(String.class)) {
                    properties.put(field, value);
                } else {
                    Geometry geom = (Geometry) sFea.getDefaultGeometry();
                    cn.kmsoft.wololo.geojson.Geometry geo = jsonWriter.write(geom);

                    if (binding.equals(MultiPolygon.class)) {
                        cn.kmsoft.wololo.geojson.MultiPolygon g = (cn.kmsoft.wololo.geojson.MultiPolygon) geo;
                        geometry.put("type", "MultiPolygon");
                        geometry.put("coordinates", g.getCoordinates());
                    } else if (binding.equals(Polygon.class)) {
                        cn.kmsoft.wololo.geojson.Polygon g = (cn.kmsoft.wololo.geojson.Polygon) geo;
                        geometry.put("type", "Polygon");
                        geometry.put("coordinates", g.getCoordinates());
                    } else if (binding.equals(MultiLineString.class)) {
                        cn.kmsoft.wololo.geojson.MultiLineString g = (cn.kmsoft.wololo.geojson.MultiLineString) geo;
                        geometry.put("type", "MultiLineString");
                        geometry.put("coordinates", g.getCoordinates());
                    } else if (binding.equals(LineString.class)) {
                        cn.kmsoft.wololo.geojson.LineString g = (cn.kmsoft.wololo.geojson.LineString) geo;
                        geometry.put("type", "LineString");
                        geometry.put("coordinates", g.getCoordinates());
                    } else if (binding.equals(Point.class)) {
                        cn.kmsoft.wololo.geojson.Point g = (cn.kmsoft.wololo.geojson.Point) geo;
                        geometry.put("type", "Point");
                        geometry.put("coordinates", g.getCoordinates());
                    }
                }
            }
            feaObject.put("type", "Feature");
            feaObject.put("properties", properties);
            feaObject.put("geometry", geometry);

            features.add(feaObject);
        }
        geojson.put("features", features);

        sfIter.close();
        store.dispose();

        return geojson;
    }

    public static FeatureCollection<SimpleFeatureType, SimpleFeature> getFeaCollection(String shpfilepath, String encoding) {
        if (StringUtil.isNullOrEmpty(encoding)) {
            encoding = "GBK";
        }
        if (StringUtil.isNullOrEmpty(shpfilepath)) {
            return null;
        }
        File f = new File(shpfilepath);
        if (!f.isFile() || !f.exists()) {
            new Exception("输入的shp数据地址有问题-->: " + shpfilepath);
        }
        String pathStr = f.getAbsolutePath();
        String folderPath = FileUtil.getPathOfDiskFile(pathStr);//物理路径
        String fileNameNoExtention = FileUtil.getFileNameWithNoPathAndExtension(pathStr);

        String shxfilepath = folderPath + "\\" + fileNameNoExtention + ".shx";
        String dbffilepath = folderPath + "\\" + fileNameNoExtention + ".dbf";
        String prjfilepath = folderPath + "\\" + fileNameNoExtention + ".prj";
        File shxfile = new File(shxfilepath);
        File dbffile = new File(dbffilepath);
        File prjfile = new File(prjfilepath);
        FeatureCollection<SimpleFeatureType, SimpleFeature> feaCollection = null;

        if (shxfile.exists() && dbffile.exists() && prjfile.exists()) {
            ShapefileDataStore dataStore = null;
            try {
                dataStore = new ShapefileDataStore(new File(shpfilepath).toURI().toURL());
                dataStore.setCharset(Charset.forName(encoding));
                String typeName = dataStore.getTypeNames()[0];

                FeatureSource<SimpleFeatureType, SimpleFeature> feaSource =
                        (FeatureSource<SimpleFeatureType, SimpleFeature>) dataStore.getFeatureSource(typeName);
                feaCollection = feaSource.getFeatures();

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (dataStore != null) {
                    dataStore.dispose();
                }
            }

            return feaCollection;
        } else {
            return null;
        }
    }

    public static JSONObject toGeoJson(FeatureCollection<SimpleFeatureType, SimpleFeature> feaCollection, String encoding) throws Exception {
        JSONObject geojson = new JSONObject();
        JSONArray features = new JSONArray();
        geojson.put("type", "FeatureCollection");

        FeatureIterator<SimpleFeature> feaIter = feaCollection.features();
        while (feaIter.hasNext()) {
            JSONObject feature = new JSONObject();
            JSONObject properties = new JSONObject();
            JSONObject geometry = new JSONObject();
            GeoJSONWriter writer = new GeoJSONWriter();

            SimpleFeature sf = feaIter.next();
            Collection<Property> props = sf.getProperties();
            Iterator<Property> proIter = props.iterator();
            while (proIter.hasNext()) {
                Property p = proIter.next();
                PropertyType pt = p.getType();
                String field = pt.getName().getLocalPart();
                Object val = p.getValue();

                if (val == null) {
                    properties.put(field, "");
                    continue;
                }
                String value = val.toString();
                Class<?> binding = pt.getBinding();

                if (binding.equals(Integer.class)) {
                    properties.put(field, Integer.parseInt(value));
                } else if (binding.equals(Long.class)) {
                    properties.put(field, Long.parseLong(value));
                } else if (binding.equals(Double.class)) {
                    properties.put(field, Double.parseDouble(value));
                } else if (binding.equals(String.class)) {
                    properties.put(field, value);
                } else {
                    Geometry geom = (Geometry) sf.getDefaultGeometry();
                    cn.kmsoft.wololo.geojson.Geometry geo = writer.write(geom);

                    if (binding.equals(MultiPolygon.class)) {
                        //几何面积
                        double fgeoArea = geom.getArea();
                        properties.put("FGEOAREA", fgeoArea);

                        cn.kmsoft.wololo.geojson.MultiPolygon g = (cn.kmsoft.wololo.geojson.MultiPolygon) geo;
                        geometry.put("type", "MultiPolygon");
                        geometry.put("coordinates", g.getCoordinates());

                    } else if (binding.equals(Polygon.class)) {
                        //几何面积
                        double fgeoArea = geom.getArea();
                        properties.put("FGEOAREA", fgeoArea);

                        cn.kmsoft.wololo.geojson.Polygon g = (cn.kmsoft.wololo.geojson.Polygon) geo;
                        geometry.put("type", "Polygon");
                        geometry.put("coordinates", g.getCoordinates());

                    } else if (binding.equals(MultiLineString.class)) {
                        cn.kmsoft.wololo.geojson.MultiLineString g = (cn.kmsoft.wololo.geojson.MultiLineString) geo;
                        geometry.put("type", "MultiLineString");
                        geometry.put("coordinates", g.getCoordinates());

                    } else if (binding.equals(LineString.class)) {
                        cn.kmsoft.wololo.geojson.LineString g = (cn.kmsoft.wololo.geojson.LineString) geo;
                        geometry.put("type", "LineString");
                        geometry.put("coordinates", g.getCoordinates());

                    } else if (binding.equals(Point.class)) {
                        cn.kmsoft.wololo.geojson.Point g = (cn.kmsoft.wololo.geojson.Point) geo;
                        geometry.put("type", "Point");
                        geometry.put("coordinates", g.getCoordinates());
                    }
                }
            }
            feature.put("type", "Feature");
            feature.put("properties", properties);
            feature.put("geometry", geometry);

            features.add(feature);
        }
        geojson.put("features", features);

        feaIter.close();

        return geojson;

    }


    /**
     * 将shp文件转换为json文件
     *
     * @param shpPath  shp文件存储路径
     * @param jsonPath 需要存放json文件存储路径
     * @return 转换成功则为true，其他为false
     */
    public static boolean shp2json(String shpPath, String jsonPath) {
        ShapefileDataStore datastore = null;
        FeatureJSON fjson = new FeatureJSON();
        boolean bSuccessed = false;

        try {
            datastore = new ShapefileDataStore(new File(shpPath).toURI().toURL());
            datastore.setCharset(Charset.forName("GBK"));
            String typeName = datastore.getTypeNames()[0];
            FeatureSource<SimpleFeatureType, SimpleFeature> source = null;
            source = (FeatureSource<SimpleFeatureType, SimpleFeature>) datastore
                    .getFeatureSource(typeName);
            FeatureCollection<SimpleFeatureType, SimpleFeature> features = source
                    .getFeatures();
            //定义输出json文件
            File outfile = new File(jsonPath);
            OutputStream output = new FileOutputStream(outfile);
            StringWriter strWriter = new StringWriter();

            fjson.writeFeatureCollection(features, strWriter);
            String feaJsonString = strWriter.toString();
            System.out.println(feaJsonString);

            fjson.writeFeatureCollection(features, output);

            strWriter.flush();
            strWriter.close();

            bSuccessed = true;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        datastore.dispose();

        return bSuccessed;
    }

    /**
     * 根据GeoJSON生成Shapefile
     *
     * @param path
     * @param name
     * @param geojson
     * @param fields
     * @param wkid
     * @param encoding
     * @throws Exception
     */
    public static void fromGeoJson(String path, String name, JSONObject geojson, JSONArray fields, String wkid, String encoding) throws Exception {
        if (StringUtil.isNullOrEmpty(encoding)) {
            encoding = "utf-8";
        }
        // 创建shape文件对象
        File file = new File(path + File.separator + name + ".shp");
        Map<String, Serializable> params = new HashMap<String, Serializable>();
        params.put(ShapefileDataStoreFactory.URLP.key, file.toURI().toURL());
        ShapefileDataStore sfds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
        sfds.setCharset(Charset.forName(encoding));    // 定义字符集

        JSONArray features = (JSONArray) geojson.get("features");
        JSONObject feature0 = features.getJSONObject(0);
        String strType = ((JSONObject) feature0.get("geometry")).getString("type").toString();

        Class<?> geoType = null;
        switch (strType) {
            case "Point":
                geoType = Point.class;
            case "MultiPoint":
                geoType = MultiPoint.class;
            case "LineString":
                geoType = LineString.class;
            case "MultiLineString":
                geoType = MultiLineString.class;
            case "Polygon":
                geoType = Polygon.class;
            case "MultiPolygon":
                geoType = MultiPolygon.class;
        }
        // 定义坐标系
        SimpleFeatureTypeBuilder sftb = new SimpleFeatureTypeBuilder();
        String wkt = getWKT(wkid);
        sftb.setCRS(CRS.parseWKT(wkt));
//        sftb.setCRS(DefaultGeographicCRS.WGS84);
        sftb.setName("shapefile");
        defineGeometryType(sftb, geojson);    // 定义几何类型
        if (fields != null)
            defineFields(sfds, sftb, fields);    // 定义属性字段
        sftb.add("the_geom", geoType);
        sftb.add("NAME", String.class);
        sftb.add("LX", String.class);
        sfds.createSchema(sftb.buildFeatureType());

        // 设置Reader和Writer
        GeoJSONReader reader = new GeoJSONReader();
        FeatureWriter<SimpleFeatureType, SimpleFeature> writer = sfds.getFeatureWriter(sfds.getTypeNames()[0], Transaction.AUTO_COMMIT);
        // 解析geojson并写入数据
//     	JSONArray features = geojson.getJSONArray("features");

        for (int j = 0; j < features.size(); j++) {
            JSONObject f = features.getJSONObject(j);
            JSONObject properties = f.getJSONObject("properties");
            Geometry geometry = reader.read(f.getJSONObject("geometry").toString());
            SimpleFeature feature = writer.next();
            writeFeature(feature, fields, properties, geometry);
        }
        writer.write();
        writer.close();

        sfds.dispose();
    }

    public static void fromGeoJson(String path, String name, JSONObject geojson, JSONArray fields, String wkid) throws Exception {
        fromGeoJson(path, name, geojson, fields, wkid, "gbk");
    }

    /**
     * 写入要素
     *
     * @param feature
     * @param fields
     * @param properties
     * @param geometry
     * @throws JSONException
     */
    private static void writeFeature(SimpleFeature feature, JSONArray fields, JSONObject properties, Geometry geometry) throws JSONException {
        int max = MAX_SHAPE_FIELD_LENGTH;

        for (int i = 0; i < fields.size(); i++) {
            JSONObject field = fields.getJSONObject(i);
            String name = field.getString("name");
            String type = field.getString("type");

            if (!properties.containsKey(name)) {
                continue;
            }
            String sn = name;

            if (sn.length() > max) {
                sn = StringUtil.slice(sn, max, "utf-8");
            }
            if (properties.get(name).equals(null)) {
                feature.setAttribute(sn, null);
            } else {
                if (type.equalsIgnoreCase("int") || type.equalsIgnoreCase("esriFieldTypeInteger") || type.equalsIgnoreCase("esriFieldTypeOID")) {
                    feature.setAttribute(sn, properties.getInteger(name));

                } else if (type.equalsIgnoreCase("long") || type.equalsIgnoreCase("esriFieldTypeLong")) {
                    feature.setAttribute(sn, properties.getLong(name));

                } else if (type.equalsIgnoreCase("double") || type.equalsIgnoreCase("esriFieldTypeDouble")) {
                    feature.setAttribute(sn, properties.getDouble(name));

                } else {
                    feature.setAttribute(sn, properties.getString(name));
                }
            }
        }
        feature.setAttribute("the_geom", geometry);
    }

    private static void updateFeaProperties(SimpleFeature feature, JSONArray fields, JSONObject properties) throws JSONException {
        int max = MAX_SHAPE_FIELD_LENGTH;

        for (int i = 0; i < fields.size(); i++) {
            JSONObject field = fields.getJSONObject(i);
            String name = field.getString("name");
            String type = field.getString("type");

            if (!properties.containsKey(name)) {
                continue;
            }
            String sn = name;

            if (sn.length() > max) {
                sn = StringUtil.slice(sn, max, "utf-8");
            }
            if (properties.get(name).equals(null)) {
                feature.setAttribute(sn, null);
            } else {
                if (type.equalsIgnoreCase("int") || type.equalsIgnoreCase("esriFieldTypeInteger") || type.equalsIgnoreCase("esriFieldTypeOID")) {
                    feature.setAttribute(sn, properties.getInteger(name));

                } else if (type.equalsIgnoreCase("long") || type.equalsIgnoreCase("esriFieldTypeLong")) {
                    feature.setAttribute(sn, properties.getLong(name));

                } else if (type.equalsIgnoreCase("double") || type.equalsIgnoreCase("esriFieldTypeDouble")) {
                    feature.setAttribute(sn, properties.getDouble(name));

                } else {
                    feature.setAttribute(sn, properties.getString(name));
                }
            }
        }
    }


    /**
     * 定义字段
     *
     * @param sfds
     * @param sftb
     * @param fields
     * @throws JSONException
     * @throws IOException
     */
    private static void defineFields(ShapefileDataStore sfds, SimpleFeatureTypeBuilder sftb, JSONArray fields) throws JSONException, IOException {
        int max = MAX_SHAPE_FIELD_LENGTH;

        for (int i = 0; i < fields.size(); i++) {
            JSONObject field = fields.getJSONObject(i);
            String name = field.getString("name");
            String type = field.getString("type");

            if (name.length() > max) {
                name = StringUtil.slice(name, max, "utf-8");
            }
            if (type.equalsIgnoreCase("int") || type.equalsIgnoreCase("esriFieldTypeInteger") || type.equalsIgnoreCase("esriFieldTypeOID")) {
                sftb.add(name, Integer.class);

            } else if (type.equalsIgnoreCase("long") || type.equalsIgnoreCase("esriFieldTypeLong")) {
                sftb.add(name, Long.class);

            } else if (type.equalsIgnoreCase("double") || type.equalsIgnoreCase("esriFieldTypeDouble")) {
                sftb.add(name, Double.class);

            } else {
                sftb.add(name, String.class);
            }
        }
    }


    /**
     * 定义几何类型
     *
     * @param sftb
     * @param geojson
     * @throws JSONException
     */
    private static void defineGeometryType(SimpleFeatureTypeBuilder sftb, JSONObject geojson) throws JSONException {
        String geometryType = getGeometryType(geojson);

        if (geometryType.endsWith("Polygon")) {
            sftb.add("the_geom", Polygon.class);

        } else if (geometryType.endsWith("LineString")) {
            sftb.add("the_geom", LineString.class);

        } else if (geometryType.endsWith("Point")) {
            sftb.add("the_geom", Point.class);
        }
    }

    /**
     * 获取GeoJSON几何类型
     *
     * @param geojson
     * @return
     * @throws JSONException
     */
    private static String getGeometryType(JSONObject geojson) throws JSONException {
        JSONArray features = geojson.getJSONArray("features");
        JSONObject feature = features.getJSONObject(0);
        return feature.getJSONObject("geometry").getString("type");
    }

    /**
     * 根据WKID获取WKT表达式
     *
     * @param wkid
     * @return
     */
    private static String getWKT(String wkid) {
        if (StringUtil.isNullOrEmpty(wkid)) {
            wkid = "2332";
        }
        if (wkid.equalsIgnoreCase("2432")) {
            return "PROJCS[\"Beijing_1954_3_Degree_GK_CM_105E\",GEOGCS[\"GCS_Beijing_1954\",DATUM[\"D_Beijing_1954\",SPHEROID[\"Krasovsky_1940\",6378245.0,298.3]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Gauss_Kruger\"],PARAMETER[\"False_Easting\",500000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",105.0],PARAMETER[\"Scale_Factor\",1.0],PARAMETER[\"Latitude_Of_Origin\",0.0],UNIT[\"Meter\",1.0]]";
        }
        if (wkid.equalsIgnoreCase("2359")) {
            return "PROJCS[\"Xian_1980_3_Degree_GK_Zone_35\",GEOGCS[\"GCS_Xian_1980\",DATUM[\"D_Xian_1980\",SPHEROID[\"Xian_1980\",6378140.0,298.257]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Gauss_Kruger\"],PARAMETER[\"False_Easting\",35500000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",105.0],PARAMETER[\"Scale_Factor\",1.0],PARAMETER[\"Latitude_Of_Origin\",0.0],UNIT[\"Meter\",1.0]]";
        }
        if (wkid.equalsIgnoreCase("2360")) {
            return "PROJCS[\"Xian_1980_3_Degree_GK_Zone_36\",GEOGCS[\"GCS_Xian_1980\",DATUM[\"D_Xian_1980\",SPHEROID[\"Xian_1980\",6378140.0,298.257]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Gauss_Kruger\"],PARAMETER[\"False_Easting\",36500000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",108.0],PARAMETER[\"Scale_Factor\",1.0],PARAMETER[\"Latitude_Of_Origin\",0.0],UNIT[\"Meter\",1.0]]";
        }
        if (wkid.equalsIgnoreCase("2361")) {
            return "PROJCS[\"Xian_1980_3_Degree_GK_Zone_37\",GEOGCS[\"GCS_Xian_1980\",DATUM[\"D_Xian_1980\",SPHEROID[\"Xian_1980\",6378140.0,298.257]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Gauss_Kruger\"],PARAMETER[\"False_Easting\",37500000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",111.0],PARAMETER[\"Scale_Factor\",1.0],PARAMETER[\"Latitude_Of_Origin\",0.0],UNIT[\"Meter\",1.0]]";
        }
        if (wkid.equalsIgnoreCase("4326")) {
            return "GEOGCS[\"GCS_WGS_1984\",DATUM[\"D_WGS_1984\",SPHEROID[\"WGS_1984\",6378137.0,298.257223563]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]]";
        }
        if (wkid.equalsIgnoreCase("4496")) {
            return "PROJCS[\"CGCS2000_GK_Zone_18\",GEOGCS[\"GCS_China_Geodetic_Coordinate_System_2000\",DATUM[\"D_China_2000\",SPHEROID[\"CGCS2000\",6378137.0,298.257222101]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Gauss_Kruger\"],PARAMETER[\"False_Easting\",18500000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",105.0],PARAMETER[\"Scale_Factor\",1.0],PARAMETER[\"Latitude_Of_Origin\",0.0],UNIT[\"Meter\",1.0]]";
        }
        if (wkid.equalsIgnoreCase("4523")) {
            return "PROJCS[\"CGCS2000_3_Degree_GK_Zone_35\",GEOGCS[\"GCS_China_Geodetic_Coordinate_System_2000\",DATUM[\"D_China_2000\",SPHEROID[\"CGCS2000\",6378137.0,298.257222101]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Gauss_Kruger\"],PARAMETER[\"False_Easting\",35500000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",105.0],PARAMETER[\"Scale_Factor\",1.0],PARAMETER[\"Latitude_Of_Origin\",0.0],UNIT[\"Meter\",1.0]]";
        }
        if (wkid.equalsIgnoreCase("4524")) {
            return "PROJCS[\"CGCS2000_3_Degree_GK_Zone_36\",GEOGCS[\"GCS_China_Geodetic_Coordinate_System_2000\",DATUM[\"D_China_2000\",SPHEROID[\"CGCS2000\",6378137.0,298.257222101]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Gauss_Kruger\"],PARAMETER[\"False_Easting\",36500000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",108.0],PARAMETER[\"Scale_Factor\",1.0],PARAMETER[\"Latitude_Of_Origin\",0.0],UNIT[\"Meter\",1.0]]";
        }
        if (wkid.equalsIgnoreCase("4525")) {
            return "PROJCS[\"CGCS2000_3_Degree_GK_Zone_37\",GEOGCS[\"GCS_China_Geodetic_Coordinate_System_2000\",DATUM[\"D_China_2000\",SPHEROID[\"CGCS2000\",6378137.0,298.257222101]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Gauss_Kruger\"],PARAMETER[\"False_Easting\",37500000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",111.0],PARAMETER[\"Scale_Factor\",1.0],PARAMETER[\"Latitude_Of_Origin\",0.0],UNIT[\"Meter\",1.0]]";
        }
        // default 2332
        return "PROJCS[\"Xian_1980_GK_Zone_18\",GEOGCS[\"GCS_Xian_1980\",DATUM[\"D_Xian_1980\",SPHEROID[\"Xian_1980\",6378140.0,298.257]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Gauss_Kruger\"],PARAMETER[\"False_Easting\",18500000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",105.0],PARAMETER[\"Scale_Factor\",1.0],PARAMETER[\"Latitude_Of_Origin\",0.0],UNIT[\"Meter\",1.0]]";
    }

    public static void shp2txt(SimpleFeatureCollection feaCollections, String txtfile, LandHeader header) {

        FeatureJSON fjson = new FeatureJSON();
        try {
            //land
            Land land = new Land();

            //设置信息头
            land.setFormatVersion(header.getFormatVersion());
            land.setDataProduceOrg(header.getDataProduceOrg());
            land.setProduceDate(header.getProduceDate());
            land.setCoordinateSystem(header.getCoordinateSystem());
            land.setDegreeNo(header.getDegreeNo());//几度分带
            land.setProjectionType(header.getProjectionType());
            land.setUnit(header.getUnit());
            land.setDegreeNum(header.getDegreeNum());
            land.setPrecision(header.getPrecision());//精度
            land.setConversionParameter(header.getConversionParameter());//精度

            //遍历要素
            int blockNum = 0;
            SimpleFeatureIterator feaIter = (SimpleFeatureIterator) feaCollections.features();
            while (feaIter.hasNext()) {
                SimpleFeature feature = feaIter.next();

                //block
                Block landBlock = new Block();
                blockNum++;

                //1.获取Feature基本信息
                int attrCount = feature.getAttributeCount();
                String the_geom = feature.getAttribute("the_geom").toString();

                //将shp的feature转换为geojson串
                StringWriter strWriter = new StringWriter();
                fjson.writeFeature(feature, strWriter);
                String feaJsonString = strWriter.toString();
                //System.out.println(feaJsonString);

                //转换json串的为json对象
                JSONObject feaObject = JSON.parseObject(feaJsonString);
                String feaId = feaObject.getString("id");
                String feaType = feaObject.getString("type");

                //2.获取Feature属性信息
                System.out.println();
                System.out.println("---属性字段：");
                JSONObject feaProperties = feaObject.getJSONObject("properties");
                for (Map.Entry<String, Object> entry : feaProperties.entrySet()) {
                    String fieldName = entry.getKey();
                    String fieldValue = entry.getValue().toString();

                    landBlock.getbAttrs().put(fieldName, fieldValue);
                    System.out.println(fieldName + ":" + fieldValue);
                }

                //******************4.第四个可能需要修改的地方******************
                //地块面积单位：通常为公顷
                Double dkmj = landBlock.getbAttrs().get("TXJSMJ") != null ?
                        Double.parseDouble(landBlock.getbAttrs().get("TXJSMJ").toString()) : 0.00;//图形计算面积，单位公顷
                String dkbh = String.format("地块%s", blockNum);
                //String dkbh = landBlock.getbAttrs().get("DKBH")!=null ?
                //		landBlock.getbAttrs().get("DKBH").toString():"";
                String dkmc = landBlock.getbAttrs().get("XMMC") != null ?
                        landBlock.getbAttrs().get("XMMC").toString() : "";
                String jltxsx = "面";
                String tfh = "";//图幅号
                String dkyt = landBlock.getbAttrs().get("TDYT") != null ?
                        landBlock.getbAttrs().get("TDYT").toString() : "";

                landBlock.setDkmj(dkmj);
                landBlock.setDkbh(dkbh);
                landBlock.setDkmc(dkmc);
                landBlock.setJltxsx(jltxsx);
                landBlock.setTfh(tfh);
                landBlock.setDkyt(dkyt);

                //3.获取Geometry相关信息
                JSONObject geoObject = feaObject.getJSONObject("geometry");
                String feaGeoType = geoObject.getString("type");
                System.out.println();
                System.out.println("feaGeoType: " + feaGeoType);
                // geometry坐标串
                JSONArray feaGeoCoords = geoObject.getJSONArray("coordinates");
                for (int i = 0; i < feaGeoCoords.size(); i++) {
                    JSONArray jsonRings = feaGeoCoords.getJSONArray(i);
                    for (int j = 0; j < jsonRings.size(); j++) {
                        //ring
                        Ring blockRing = new Ring();
                        JSONArray jsonRing = jsonRings.getJSONArray(j);
                        for (int k = 0; k < jsonRing.size(); k++) {
                            JSONArray jsonCoords = jsonRing.getJSONArray(k);

                            // point
                            cn.kmsoft.stgeometry.landm.Point p = new  cn.kmsoft.stgeometry.landm.Point();
                            Double x = Double.parseDouble(jsonCoords.get(0).toString());
                            Double y = Double.parseDouble(jsonCoords.get(1).toString());
                            //坐标点
                            p.setX(x);
                            p.setY(y);
                            System.out.println(String.format("%.3f, %.3f", x, y));

                            blockRing.getPoints().add(p);
                        }

                        landBlock.getRings().add(blockRing);
                    }
                }

                land.getBlocks().add(landBlock);
            }

            feaIter.close();

            //输出land中内容到txt文件中
            File outtxtfile = new File(txtfile);
            //PrintStream ps = new PrintStream(new FileOutputStream(outtxtfile));
            PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(txtfile), "GBK"), true);

            //基本信息
            pw.println("[属性描述]");
            pw.println("格式版本号=" + land.getFormatVersion());
            pw.println("数据产生单位=" + land.getDataProduceOrg());
            pw.println("数据产生日期=" + land.getProduceDate());
            pw.println("坐标系=" + land.getCoordinateSystem());
            pw.println("几度分带=" + land.getDegreeNo());
            pw.println("投影类型=" + land.getProjectionType());
            pw.println("计量单位=" + land.getUnit());
            pw.println("带号=" + land.getDegreeNum());
            pw.println("精度=" + land.getPrecision());
            pw.println("转换参数=" + land.getConversionParameter());

            //坐标序列
            pw.println("[地块坐标]");

            int blockCount = land.getBlocks().size();
            for (int i = 0; i < blockCount; i++) {
                Block block = land.getBlocks().get(i);
                int ringCount = block.getRings().size();

                //界址点数
                int jzdCount = 0;
                for (int j = 0; j < ringCount; j++) {
                    Ring ring = block.getRings().get(j);
                    int pointCount = ring.getPoints().size();

                    jzdCount += pointCount;
                }
                //加上最后的闭合点
                //jzdCount = jzdCount + 1;

                String dkmj = String.format("%.4f", block.getDkmj());
                //String dkbh = block.getDkbh();
                int bhIndex = i + 1;
                String dkbh = "地块" + bhIndex;
                String dkmc = block.getDkmc();
                String jltxsx = block.getJltxsx();
                String tfh = block.getTfh();
                String dkyt = block.getDkyt();

                //坐标序列台头
                //界址点数,地块面积,地块编号,地块名称,记录图形属性(点、线、面),图幅号,地块用途,地类编码,@
                String blockHeader = String.format("%s,%s,%s,%s,%s,%s,%s,%s,%s",
                        jzdCount, dkmj, dkbh, dkmc, jltxsx, tfh, dkyt, "地类编码", "@");
                //System.out.println(blockHeader);
                pw.println(blockHeader);

                for (int j = 0; j < ringCount; j++) {
                    Ring ring = block.getRings().get(j);
                    int pointCount = ring.getPoints().size();

                    int ringIndex = j + 1;
                    for (int k = 0; k < pointCount; k++) {
                        cn.kmsoft.stgeometry.landm.Point pt = ring.getPoints().get(k);
                        //String y = String.format("%.6f",pt.getY());
                        //String x = String.format("%.6f",pt.getX());
                        String y = String.format("%.3f", pt.getY());
                        String x = String.format("%.3f", pt.getX());

                        int jzdIndex = k + 1;
                        String jzdLabel = "J" + jzdIndex;
                        String line = String.format("%s,%s,%s,%s", jzdLabel, ringIndex, y, x);

                        pw.println(line);
                    }

                    //添加第一个界址点，形成闭合
	        		/*
	        		Point firstPt = ring.getPoints().get(0);	        			
        			String fy = String.format("%.3f",firstPt.getY());
        			String fx = String.format("%.3f",firstPt.getX());
        			String line = String.format("%s,%s,%s,%s", "J1", ringIndex, fy, fx);
        			*/
                    //pw.println(line);

                }
            }

            pw.flush();
            pw.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void shp2txt(String shppath, String txtfile) {
        String encoding = "gbk";
        File file = new File(shppath);
        ShapefileDataStore shpDataStore = null;
        try {
            URL url = file.toURI().toURL();
            shpDataStore = new ShapefileDataStore(url);
            shpDataStore.setCharset(Charset.forName(encoding));
            String typeName = shpDataStore.getTypeNames()[0];
            SimpleFeatureSource featureSource = shpDataStore.getFeatureSource(typeName);
            SimpleFeatureCollection feaCollections = featureSource.getFeatures();

            LandHeader header = new LandHeader();
            //shp转txt
            shp2txt(feaCollections, txtfile, header);

        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            shpDataStore.dispose();
        }
    }

    public static void main(String[] args) {
        double start = System.currentTimeMillis();

        String inputPath1 = "E:\\temp\\gtgis\\testtzdk2\\jsydgzq.shp";
        //String inputPath2 = "E:\\temp\\gtgis\\testtzdk2\\tzdk.shp";
        String inputPath2 = "E:\\temp\\gtgis\\testtzdk2\\yjjbnt.shp";
        String outputPath = "E:\\temp\\gtgis\\testtzdk2\\yjjbnt_jsydgzq.shp";

        try {
            File inputFile1 = new File(inputPath1);
            File inputFile2 = new File(inputPath2);

            ShapefileDataStore shpDataStore1 = new ShapefileDataStore(inputFile1.toURL());
            ShapefileDataStore shpDataStore2 = new ShapefileDataStore(inputFile2.toURL());

            //属性编码
            Charset charset = Charset.forName("GBK");
            shpDataStore1.setCharset(charset);
            shpDataStore2.setCharset(charset);
            String typeName1 = shpDataStore1.getTypeNames()[0];
            String typeName2 = shpDataStore2.getTypeNames()[0];
            SimpleFeatureSource featureSource1 = shpDataStore1.getFeatureSource(typeName1);
            SimpleFeatureType sfType = featureSource1.getSchema();
            CoordinateReferenceSystem targetCRS = sfType.getCoordinateReferenceSystem();

            SimpleFeatureSource featureSource2 = shpDataStore2.getFeatureSource(typeName2);
            SimpleFeatureCollection featureCollection1 = featureSource1.getFeatures();
            SimpleFeatureCollection featureCollection2 = featureSource2.getFeatures();

            /**
             * mapFields记录的是两个图层的属性名称，
             *          在处理第二个图层的时候，如果已经有了这个名称，
             *          会在字段后面加‘_1’予以区分
             * fields1为图层1的字段
             * fields2为图层2的字段
             */
            Map<String, Class> mapFields = new HashMap();
            List<Map> fields1 = new ArrayList();
            List<Map> fields2 = new ArrayList();

            SimpleFeatureType featureType1 = featureCollection1.getSchema();
            List<AttributeDescriptor> attrList1 = featureType1.getAttributeDescriptors();
            for (int i = 0; i < attrList1.size(); i++) {
                AttributeDescriptor attr = attrList1.get(i);
                String name = attr.getName().toString();
                Class type = attr.getType().getBinding();
                if (name != "the_geom") {
                    mapFields.put(name, type);

                    Map map = new HashMap();
                    map.put("fieldShp", name);
                    map.put("fieldNew", name);
                    fields1.add(map);
                }
            }
            SimpleFeatureType featureType2 = featureCollection2.getSchema();
            List<AttributeDescriptor> attrList2 = featureType2.getAttributeDescriptors();
            for (int j = 0; j < attrList2.size(); j++) {
                AttributeDescriptor attr = attrList2.get(j);
                String name = attr.getName().toString();
                Class type = attr.getType().getBinding();
                if (name != "the_geom") {
                    String _name = name;
                    if (mapFields.containsKey(name)) {
                        _name = _name + "_1";
                    }
                    mapFields.put(_name, type);

                    Map map = new HashMap();
                    map.put("fieldShp", name);
                    map.put("fieldNew", _name);
                    fields2.add(map);
                }
            }

            //遍历被叠加的图层数据，建立空间索引
            Quadtree quadTree = new Quadtree();
            SimpleFeatureIterator iterator1 = featureCollection1.features();
            while (iterator1.hasNext()) {
                SimpleFeature feature1 = iterator1.next();
                Geometry geom1 = (Geometry) feature1.getDefaultGeometry();
                Envelope itemEnv = geom1.getEnvelopeInternal();
                quadTree.insert(itemEnv, feature1);
            }

            //创建输出文件
            File outputFile = new File(outputPath);
            Map<String, Serializable> params = new HashMap<String, Serializable>();
            params.put(ShapefileDataStoreFactory.URLP.key, outputFile.toURI().toURL());
            ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
            //定义图形信息和属性信息
            SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
            tb.setCRS(targetCRS);
            tb.setName("shapefile");
            tb.add("the_geom", MultiPolygon.class);
            for (String key : mapFields.keySet()) {

                tb.add(key, mapFields.get(key));
            }
            ds.createSchema(tb.buildFeatureType());
            //设置编码
            ds.setCharset(charset);
            //设置Writer
            FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);

            //记录已经参与过计算的数据
            Map hasDone = new HashMap();
            //图形数据
            SimpleFeatureIterator itertor2 = featureCollection2.features();
            while (itertor2.hasNext()) {
                SimpleFeature feature2 = itertor2.next();
                Geometry geom2 = (Geometry) feature2.getDefaultGeometry();
                String id2 = feature2.getID();

                List<SimpleFeature> intersectResults = new ArrayList<SimpleFeature>();
                //图形的包络线相交
                List<SimpleFeature> envelopeIntersections = quadTree.query(geom2.getEnvelopeInternal());
                Iterator<SimpleFeature> iter = envelopeIntersections.iterator();
                while (iter.hasNext()) {
                    SimpleFeature feature1 = iter.next();
                    Geometry targetGeo = (Geometry) feature1.getDefaultGeometry();
                    //判断图形是不是真的相交
                    if (geom2.intersects(targetGeo)) {
                        Geometry geomOut = geom2.intersection(targetGeo);
                        if (geomOut != null && !geomOut.isEmpty()) {
                            SimpleFeature featureOut = writer.next();
                            featureOut.setAttribute("the_geom", geomOut);
                            for (int i = 0; i < fields1.size(); i++) {
                                Map map = fields1.get(i);
                                String fieldShp = map.get("fieldShp").toString();
                                String fieldNew = map.get("fieldNew").toString();
                                if (fieldNew.length() < 10) {
                                    featureOut.setAttribute(fieldNew, feature1.getAttribute(fieldShp));
                                }

                            }
                            for (int i = 0; i < fields2.size(); i++) {
                                Map map = fields2.get(i);
                                String fieldShp = map.get("fieldShp").toString();
                                String fieldNew = map.get("fieldNew").toString();
                                if (fieldNew.length() < 10) {
                                    featureOut.setAttribute(fieldNew, feature2.getAttribute(fieldShp));
                                }
                            }
                            writer.write();
                            intersectResults.add(featureOut);
                        }
                    }
                }
                System.out.println(String.format("DKID: %s ,叠加的管制区数量为: %d ", id2, intersectResults.size()));
            }
            writer.close();

            ds.dispose();
            itertor2.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        double end = System.currentTimeMillis();
        System.out.println("共耗时" + (end - start) + "MS");
    }


    /**
     * 获取一个gpkg文件中所有图形要素的界址点坐标串
     *
     * @param shpPath
     * @return
     */
    public static Map<String, List<String>> getBlockJzdList(String shpPath) {
        Map<String, List<String>> results = new HashMap<String, List<String>>();

        try {
            ShapefileDataStore datastore = new ShapefileDataStore(new File(shpPath).toURI().toURL());
            datastore.setCharset(Charset.forName("GBK"));
            String typeName = datastore.getTypeNames()[0];

            FeatureSource<SimpleFeatureType, SimpleFeature> source = null;
            source = (FeatureSource<SimpleFeatureType, SimpleFeature>) datastore.getFeatureSource(typeName);
            FeatureCollection<SimpleFeatureType, SimpleFeature> feaCollection = source
                    .getFeatures();

            List<String> uuidJzdlist = new ArrayList<String>();

            int i = 0;
            FeatureIterator<SimpleFeature> feaIter = feaCollection.features();
            while (feaIter.hasNext()) {
                i++;
                String feaIndex = String.format("%d", i);
                SimpleFeature sf = feaIter.next();

                //一个要素可能包含多个图形对象（地块）
                Map<String, String> jzdlist = getFeaJzdlist(sf);
                Set<String> keySet = jzdlist.keySet();
                Iterator<String> keyIter = keySet.iterator();
                while (keyIter.hasNext()) {
                    String key = keyIter.next();
                    String jzdstr = jzdlist.get(key);

                    uuidJzdlist.add(jzdstr);
                }

                results.put(feaIndex, uuidJzdlist);
            }
            feaIter.close();

            datastore.dispose();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return results;
    }


    /**
     * 根据UUID获取一个gpkg文件相应的图形要素的界址点坐标串
     *
     * @param shpPath
     * @param uuid
     * @return
     */
    public static Map<String, List<String>> getBlockJzdListByUUID(String shpPath, String uuid) {
        Map<String, List<String>> results = new HashMap<String, List<String>>();

        try {
            ShapefileDataStore shpDataStore = new ShapefileDataStore(new File(shpPath).toURI().toURL());
            shpDataStore.setCharset(Charset.forName("GBK"));
            String typeName = shpDataStore.getTypeNames()[0];
            SimpleFeatureSource featureSource = shpDataStore.getFeatureSource(typeName);

            String targetFieldName = "uuid";
            //查询筛选
            FilterFactory2 filterFactory = CommonFactoryFinder.getFilterFactory2();
            Filter filter = (Filter) filterFactory.equals(filterFactory.property(targetFieldName), filterFactory.literal(uuid));
            SimpleFeatureCollection subCollections = featureSource.getFeatures(filter);

            List<String> uuidJzdlist = new ArrayList<String>();

            int i = 0;
            FeatureIterator<SimpleFeature> feaIter = subCollections.features();
            while (feaIter.hasNext()) {
                i++;
                String feaIndex = String.format("%d", i);
                SimpleFeature sf = feaIter.next();

                //一个要素可能包含多个图形对象（地块）
                Map<String, String> jzdlist = getFeaJzdlist(sf);
                Set<String> keySet = jzdlist.keySet();
                Iterator<String> keyIter = keySet.iterator();
                while (keyIter.hasNext()) {
                    String key = keyIter.next();
                    String jzdstr = jzdlist.get(key);

                    uuidJzdlist.add(jzdstr);
                }

                //按要素索引号保持
                results.put(feaIndex, uuidJzdlist);
            }

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return results;
    }


    /**
     * 获取一个要素的界址点字符（一个要素可能包含多个地块）
     *
     * @param sf SimpleFeature
     * @return
     */
    private static Map<String, String> getFeaJzdlist(SimpleFeature sf) {
        Geometry geom = (Geometry) sf.getDefaultGeometry();
        String geomType = geom.getClass().getSimpleName().toLowerCase();

        Map<String, String> jzdStrsList = new HashMap<String, String>();
        if (geomType.equals("polygon")) {
            String blockIndex = String.format("地块%d", 1);

            Polygon polygon = (Polygon) geom;
            String jzdstrs = getPolygonJzdstr(polygon);
            jzdStrsList.put(blockIndex, jzdstrs);
        } else if (geomType.equals("multipolygon")) {
            MultiPolygon multiPolygon = (MultiPolygon) geom;

            int numOfPolygon = multiPolygon.getNumGeometries();
            for (int p = 0; p < numOfPolygon; p++) {
                String blockIndex = String.format("地块%d", p + 1);

                Polygon polygon = (Polygon) multiPolygon.getGeometryN(p);
                String jzdstrs = getPolygonJzdstr(polygon);
                jzdStrsList.put(blockIndex, jzdstrs);
            }
        }

        return jzdStrsList;
    }

    private static String getPolygonJzdstr(Polygon polygon) {
        String result;
        StringBuilder allJzdstrSB = new StringBuilder();

        //1-外环
        LineString extlineStr = polygon.getExteriorRing();
        String jzdstr1 = getLineStringJzdstr(extlineStr, 1);
        allJzdstrSB.append(jzdstr1);

        //2-内环
        int num = polygon.getNumInteriorRing();
        if (num > 0) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < num; i++) {
                LineString intlineStr = polygon.getInteriorRingN(i);
                String jzdstr2 = getLineStringJzdstr(intlineStr, i + 2);

                sb.append(jzdstr2);
            }
            String jzdstrs = sb.toString();
            allJzdstrSB.append(jzdstrs);
        }

        //3-删除最后一个分号
        allJzdstrSB.deleteCharAt(allJzdstrSB.length() - 1);
        result = allJzdstrSB.toString();

        return result;
    }

    private static String getLineStringJzdstr(LineString lineString, int ringIndex) {
        Coordinate[] corrds = lineString.getCoordinates();
        StringBuffer sb = new StringBuffer();
        int len = corrds.length;
        for (int i = 0; i < len; i++) {
            Coordinate corrd = corrds[i];
            String jzdstr = String.format("J%d, %d, %.4f, %.4f", i + 1, ringIndex, corrd.x, corrd.y);
            sb.append(jzdstr);
            sb.append(";");
        }

        return sb.toString();
    }

    private static String getCoordinateJzdstr(Coordinate coord) {
        return coord.x + "," + coord.y;
    }


    public static String shp2GeoJson(String shppath, String encoding) {
        JSONObject geoJson = null;
        try {
            geoJson = ShpUtil.toGeoJson(shppath, encoding);
        } catch (Exception e) {
            e.printStackTrace();
        }

        String geoJsonStr = "";
        if (geoJson != null) {
            geoJsonStr = JSON.toJSONString(geoJson);
        }

        return geoJsonStr;
    }

    public static String shp2GeoJson(String shppath) {
        JSONObject geoJson = null;
        try {
            geoJson = ShpUtil.toGeoJson(shppath);
        } catch (Exception e) {
            e.printStackTrace();
        }

        String geoJsonStr = "";
        if (geoJson != null) {
            geoJsonStr = JSON.toJSONString(geoJson);
        }

        return geoJsonStr;
    }

}
